using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using System.Drawing;
using System.Text;

using Routine.Utilities;

using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.Common.Helpers;
using Styx.Pathing;

using CommonBehaviors.Actions;

using Singular.Dynamics;
using Singular.Helpers;
using Singular.Managers;
using Singular.Settings;

using Action = Styx.TreeSharp.Action;
//
using Rest = Singular.Helpers.Rest;
//




namespace Pyro1_1
{
    public class Routine : CombatRoutine
    {
        /// <summary>
        /// The name of this CombatRoutine
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        public override string Name { get { return "Pyro1.1"; } }


        /// <summary>
        /// The <see cref="T:Styx.WoWClass"/> to be used with this routine
        /// </summary>
        /// <value>
        /// The class.
        /// </value>
        public override WoWClass Class { get { return WoWClass.Mage; } }

		private const String IgniteLua = "return UnitDebuff(\"{0}\", \"{1}\");";
        private Composite _combat, _buffs;


        public override Composite CombatBehavior { get { return _combat; } }
        public override Composite PreCombatBuffBehavior { get { return _buffs; } }
        public override Composite CombatBuffBehavior { get { return _buffs; } }

        public DateTime LastCastTime = DateTime.Now;

        public override void Initialize()
        {
            _combat = CreateCombat();
            _buffs = CreateBuffs();
        }

		public static double DebuffDuration(String spellName, WoWUnit u)
		{
			if (!u.Debuffs.ContainsKey(spellName)) return -1;
			return u.Debuffs[spellName].TimeLeft.TotalSeconds;
		}

		private int addCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && StyxWoW.Me.CurrentTarget != null
                    && u.Guid != StyxWoW.Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.Location.Distance(StyxWoW.Me.Location) <= 35
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }

        private int RAOEaddCount()
        {
            int count = 0;
            foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
            {
                if (u.IsAlive
                    && StyxWoW.Me.CurrentTarget != null
                    && u.Guid != StyxWoW.Me.Guid
                    && !u.IsFriendly
                    && (u.IsHostile || u.IsNeutral)
                    && !u.IsCritter
                    && u.Location.Distance(StyxWoW.Me.CurrentTarget.Location) <= 10//&& u.IsWithinMeleeRange
                    && (u.IsTargetingMyPartyMember || u.IsTargetingMyRaidMember || u.IsTargetingMeOrPet || u.IsTargetingAnyMinion))
                {
                    count++;
                }
            }
            return count;
        }

        Composite CreateBuffs()
        {
            return new PrioritySelector(
				Spell.Cast("Arcane Brilliance", ret => !StyxWoW.Me.HasAura("Arcane Brilliance") && !StyxWoW.Me.Mounted),
				Spell.Cast("Molten Armor", ret => !StyxWoW.Me.HasAura("Molten Armor") && !StyxWoW.Me.Mounted),
				//Cast("Conjure Mana Gem", ret => !StyxWoW.Me.HaveManaGem() && !StyxWoW.Me.Mounted),
				//Spell.Cast("Evocation", ret => !StyxWoW.Me.HasAura("Invoker's Energy") && !StyxWoW.Me.Mounted),
                Spell.Cast("Ice Barrier", ret => !StyxWoW.Me.HasAura("Ice Barrier") && !StyxWoW.Me.Mounted),
				new Decorator(ret =>!StyxWoW.Me.HasAura("Visions of Insanity"),
					new Action(abc =>
					{
						WoWItem item = StyxWoW.Me.BagItems.Find(ret => ret.Entry == 86569);
                            if (item != null) item.Use(); 
					})),
					new Action(abc =>
					{
						WoWItem mgem = StyxWoW.Me.BagItems.Find(ret => ret.Entry == 81901 || ret.Entry == 36799);
                            if (mgem == null) Spell.Cast("Conure Mana Gem"); 
					})
				//new Action(abc => WoWItem mgem.Entry == 81901);

			);
			
        }

		
		
        Composite CreateCombat()
        {
			return new Decorator ( ctz => !StyxWoW.Me.Mounted,
				new PrioritySelector(


                // Interrupt please.
                Spell.Cast("Counterspell", ret => StyxWoW.Me.CurrentTarget.IsCasting && StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast),
                //Cast("Pyschic Horror", ret => StyxWoW.Me.CurrentTarget.IsCasting && StyxWoW.Me.CurrentTarget.CanInterruptCurrentSpellCast),
				Spell.Cast("Ice Barrier", ret => !StyxWoW.Me.HasAura("Ice Barrier")),
				// Defensive CD
				Spell.Cast("Ice Block", ret => StyxWoW.Me.HealthPercent < 35),
				Spell.Cast("Blink", ret => StyxWoW.Me.Stunned),
                //Spell.Cast("Evocation", ret => !StyxWoW.Me.HasAura("Invocation") || StyxWoW.Me.HealthPercent < 50),
                Spell.Cast("Deep Freeze", ret => StyxWoW.Me.CurrentTarget.HasAura("Frost Nova")),
                Spell.Cast("Mirror Image", ret => StyxWoW.Me.HealthPercent < 35 || StyxWoW.Me.CurrentTarget.Elite),
				//Spell.CastOnGround("Psyfiend", ctx => StyxWoW.Me.CurrentTarget.Location, ret =>	StyxWoW.Me.HealthPercent < 50 && Unit.NearbyUnfriendlyUnits.Count(u => u.Distance <= 8) >= 2),
				//Spell.Cast("Evocation", ret => StyxWoW.Me.GetAuraTimeLeft("Invoker's Energy", true) < new TimeSpan(0,0,0,2) || StyxWoW.Me.HealthPercent < 35 || StyxWoW.Me.ManaPercent < 10),
				new Decorator(ret =>StyxWoW.Me.ManaPercent < 75,
					new Action(abc =>
					{
						WoWItem item = StyxWoW.Me.BagItems.Find(ret => ret.Entry == 81901 || ret.Entry == 36799);
                            if (item != null) item.Use(); 
					})),
				// Heal yourself

                new Action(ret => { UseTrinkets(); return RunStatus.Failure; }),

				//AOE ================
				new Decorator( ret => addCount() > 4,
					new PrioritySelector(
						Spell.Cast("Living Bomb", ret=> !StyxWoW.Me.CurrentTarget.HasMyAura("Living Bomb") || StyxWoW.Me.CurrentTarget.ActiveAuras["Living Bomb"].TimeLeft.TotalSeconds < 4),
						Spell.Cast("Inferno Blast"),
						Spell.Cast("Combustion",  ret => StyxWoW.Me.CurrentTarget.HasMyAura("Ignite")),
						Spell.CastOnGround("Flamestrike", ret => StyxWoW.Me.CurrentTarget.Location, ret => RAOEaddCount() > 4),
						Spell.Cast("Dragon's Breath", ret => RAOEaddCount() > 4 && StyxWoW.Me.CurrentTarget.Distance < 10),
						Spell.Cast("Arcane Explosion")
					)
				), 
				// ===================
                new Throttle(
                    new PrioritySelector(
						new Decorator(ret => StyxWoW.Me.HasAura("Heating Up") && StyxWoW.Me.CastingSpell != null && StyxWoW.Me.CastingSpell.Name == "Fireball",// && SpellManager.Spells["Inferno Blast"].Cooldown,
							new Styx.TreeSharp.Action(r => SpellManager.StopCasting())),
						Cast("Mirror Image"),
						Cast("Presence of Mind"),
						Cast("Living Bomb", ret=> !StyxWoW.Me.CurrentTarget.HasMyAura("Living Bomb") ||
							StyxWoW.Me.CurrentTarget.ActiveAuras["Living Bomb"].TimeLeft.TotalSeconds < 4),
						Cast("Pyroblast", ret => StyxWoW.Me.HasAura("Pyroblast!") || StyxWoW.Me.HasAura("Presence of Mind")),
						//Spell.Cast("Pyroblast", ret => StyxWoW.Me.Buffs.ContainsKey("Presence of Mind")),
						
						Cast("Inferno Blast", ret => StyxWoW.Me.HasAura("Heating Up")),
						Cast("Combustion",  ret => StyxWoW.Me.CurrentTarget.HasMyAura("Ignite")),
		//				Spell.Cast("Pyroblast", ret => StyxWoW.Me.HasAura("Heating Up") && StyxWoW.Me.HasAura("Pyroblast!")),
						Cast("Fireball", ret => !StyxWoW.Me.HasAura("Presence of Mind")),
						Cast("Fireball")
						)
					)
				)
			);
        }


        void UseTrinkets()
        {
            var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
            var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;


            if(firstTrinket != null && CanUseEquippedItem(firstTrinket))
                firstTrinket.Use();


            if(secondTrinket != null && CanUseEquippedItem(secondTrinket))
                secondTrinket.Use();


        }
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }


        private delegate T Selection<out T>(object context);
        Composite Cast(string spell, Selection<bool> reqs = null)
        {
            return
                new Decorator(
                    ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
                    new Action(ret => SpellManager.Cast(spell)));
        }

        public static double TargetDebuffDuration(String spellName)
        {
            return StyxWoW.Me.CurrentTarget.GetAuraTimeLeft(spellName, true).TotalSeconds;
        }

		public static int GetTargetIgniteStrength()
		{
			var returnVal = Lua.GetReturnValues(String.Format(IgniteLua, "target", "ignite")).ToArray();
			if (returnVal.Count() < 12) return 0;
			return int.Parse(returnVal[13]);
		}

		public static Boolean CombustionlbReset()
		{
			return StyxWoW.Me.CurrentTarget.HasMyAura("Living Bomb") && Unit.NearbyUnfriendlyUnits.Any(u => u.DistanceSqr < 8 * 8 && DebuffDuration("Living Bomb",u) < 2);
		}

		public static Boolean Combustion()
		{
			if (!(StyxWoW.Me.CurrentTarget.HasMyAura("Ignite") && StyxWoW.Me.CurrentTarget.HasMyAura("Pyroblast")))
			return false;
			return GetTargetIgniteStrength() > 20000;
		}

        public static TimeSpan GetSpellCooldown(string spell)
        {
            SpellFindResults results;
            if (SpellManager.FindSpell(spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Original.CooldownTimeLeft;
            }


            return TimeSpan.MaxValue;
        }
    }
}